package com.example.demo.util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.util.CellRangeAddress;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Description: Excel操作工具类
 */
@Slf4j
public class ExcelUtil {

    /**
     * 功能描述: 导出数据到Excel
     * <p>
     * 使用阿里easyPoi 自定义导出excel携带下拉框
     *
     * @param out         输出
     * @param list        需写入的数据
     * @param mapDropDown 下拉框数据
     */
    public static void exportBySelect(OutputStream out, List<? extends BaseRowModel> list, Map<Integer, String[]> mapDropDown) {

        EasyExcelFactory.write(out, list.get(0).getClass()).registerWriteHandler(new EasyExcelSheetSelectUtils(mapDropDown)).sheet().doWrite(list);

    }

    /**
     * 根据模板导出excel
     * <p>
     * 支持简易循环填写excel
     *
     * @param templatePath  模板路径
     * @param temporaryName 临时文件名称
     * @param out           文件输出流
     * @param head          easyPoi 表头对象class
     * @param list          填充列表
     * @param col           导出类class
     * @param session       session
     */
    public static void exportTemplate(String templatePath, String temporaryName, OutputStream out, Class head, Class col, List<? extends BaseRowModel> list, HttpSession session) throws IOException {
        String path = null;
        try {
            InputStream resourceAsStream = col.getClassLoader().getResourceAsStream(templatePath);
            path = ExcelUtil.getFilePath(temporaryName, resourceAsStream, session, "template/");
            Map<Integer, String[]> map = new HashMap<>();
            map.put(2, new String[]{"男", "女"});
            EasyExcel.write(out, head).needHead(false).withTemplate(path).registerWriteHandler(new EasyExcelSheetSelectUtils(map)).sheet().doWrite(list);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {//删除临时文件
            if (path != null && !"".equals(path)) {
                File tempFile = new File(path);
                tempFile.delete();
                System.err.println("删除临时文件成功=====path:" + path);
            }
            out.close();
        }
    }

    /**
     * 根据模板导出excel
     * <p>
     * 支持列表循环填写excel
     * 以及填充excel中特殊标记的值
     *
     * @param templatePath  模板路径
     * @param temporaryName 临时文件名称
     * @param out           文件输出流
     * @param head          easyPoi 表头对象class
     * @param list          填充列表
     * @param col           导出类class
     * @param session       session
     * @param data          填充excel特殊单元格值
     */
    public static void exportTemplateByFill(String templatePath, String dirPath, String temporaryName, OutputStream out, Class head, Class col, List<? extends BaseRowModel> list, Map<String, String> data, HttpSession session) throws IOException {
        String path = null;
        try {
            InputStream resourceAsStream = col.getClassLoader().getResourceAsStream(templatePath);
            path = ExcelUtil.getFilePath(temporaryName, resourceAsStream, session, dirPath);
            ExcelWriter excelWriter = EasyExcel.write(out, head).needHead(false).withTemplate(path).build();
            WriteSheet writeSheet = EasyExcel.writerSheet().build();
            //填充列表
            excelWriter.fill(list, writeSheet);
            //填充excel中特殊的单元格值
            excelWriter.fill(data, writeSheet);
            excelWriter.finish();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {//删除临时文件
            if (StringUtils.isNotEmpty(path)) {
                File tempFile = new File(path);
                tempFile.delete();
                System.err.println("删除临时文件成功=====path:" + path);
            }
            out.close();
        }
    }

    /**
     * 根据模板导出excel
     * <p>
     * 支持列表循环填写excel
     * 以及填充多个sheet页，excel中特殊标记的值
     *
     * @param templatePath  模板路径
     * @param temporaryName 临时文件名称
     * @param out           文件输出流
     * @param col           导出类class
     * @param data          填充列表数据
     * @param otherData     填充excel特殊单元格值
     */
    public static void exportSheetsTemplateByFill(String templatePath, String dirPath, String temporaryName, OutputStream out, Class col, Map<String, List> data, Map<String, String> otherData) throws IOException {
        String path = null;
        try {
            InputStream resourceAsStream = col.getClassLoader().getResourceAsStream(templatePath);
            path = ExcelUtil.getFilePath(temporaryName, resourceAsStream, dirPath);
            ExcelWriter excelWriter = EasyExcel.write(out).withTemplate(path).build();
            Set<String> sheetNums = data.keySet();
            for (String num : sheetNums) {
                WriteSheet writeSheet = EasyExcel.writerSheet(Integer.parseInt(num)).build();
                FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
                //填充列表
                excelWriter.fill(data.get(num), fillConfig, writeSheet);
                //填充excel中特殊的单元格值
                if (otherData != null) {
                    excelWriter.fill(otherData, fillConfig, writeSheet);
                }
            }
            excelWriter.finish();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
//            if (StringUtils.isNotEmpty(path)) {
//                File tempFile = new File(path);
//                tempFile.delete();
//                System.err.println("删除临时文件成功=====path:" + path);
//            }
            out.close();
        }
    }

    /**
     * 获取临时文件路径
     *
     * @param inputStream
     * @param session
     * @param fileName
     * @param dirPath
     * @return
     * @throws IOException
     */
    public static String getFilePath(String fileName, InputStream inputStream, HttpSession session, String dirPath) throws IOException {
        // 模板临时目录
        String rootPath = session.getServletContext().getRealPath(dirPath);
        // 临时文件路径名
        String filePath = rootPath + "_" + System.currentTimeMillis() + fileName;
        File tempFile = new File(filePath);
        // 保存到临时文件
        saveTempFile(inputStream, tempFile);
        return filePath;
    }


    /**
     * 获取临时文件路径
     *
     * @param inputStream
     * @param fileName
     * @param dirPath
     * @return
     * @throws IOException
     */
    public static String getFilePath(String fileName, InputStream inputStream, String dirPath) throws IOException {
        // 模板临时目录
//        String rootPath = session.getServletContext().getRealPath(dirPath);
        // 临时文件路径名
        String filePath = dirPath + "_" + System.currentTimeMillis() + fileName;
        File tempFile = new File(filePath);
        // 保存到临时文件
        saveTempFile(inputStream, tempFile);
        return filePath;
    }

    // 保存到临时目录
    private static void saveTempFile(InputStream inputStream, File tempFile) throws IOException {
        if (!tempFile.getParentFile().exists()) { //如果文件的目录不存在
            tempFile.getParentFile().mkdirs(); //创建目录
        }
        OutputStream os = new FileOutputStream(tempFile);
        byte[] b = new byte[2048];
        int length;
        while ((length = inputStream.read(b)) > 0) {
            os.write(b, 0, length);
        }
        os.flush();
        os.close();
        inputStream.close();
    }

}
